home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-19 / iritsm3s.zip / SBSP_AUX.C < prev    next >
C/C++ Source or Header  |  1991-05-26  |  12KB  |  330 lines

  1. /******************************************************************************
  2. * SBsp-Aux.c - Bspline surface auxilary routines.                  *
  3. *******************************************************************************
  4. * Written by Gershon Elber, July. 90.                          *
  5. ******************************************************************************/
  6.  
  7. #ifdef __MSDOS__
  8. #include <stdlib.h>
  9. #endif /* __MSDOS__ */
  10.  
  11. #include <ctype.h>
  12. #include <stdio.h>
  13. #include <string.h>
  14. #include "cagd_loc.h"
  15.  
  16. /* Define some marcos to make some of the routines below look better. They  */
  17. /* calculate the index of the U, V point of the control mesh in Points.        */
  18. #define DERIVED_SRF(U, V)    CAGD_MESH_UV(DerivedSrf, U, V)
  19. #define RAISED_SRF(U, V)    CAGD_MESH_UV(RaisedSrf, U, V)
  20. #define SRF(U, V)        CAGD_MESH_UV(Srf, U, V)
  21.  
  22. /******************************************************************************
  23. * Given a bspline surface - subdivide it into two at given parametric value.  *
  24. * Returns pointer to first surface in a list of two srfs (subdivided ones).   *
  25. * The subdivision is exact result of evaluating the surface int a curve at t  *
  26. * using the recursive algorithm - the left resulting points is left surface,  *
  27. * and the right resulting points is right surface (left is below t).          *
  28. ******************************************************************************/
  29. CagdSrfStruct *BspSrfSubdivAtParam(CagdSrfStruct *Srf, CagdRType t,
  30.                             CagdSrfDirType Dir)
  31. {
  32.     int Row, Col,
  33.         ULength1 = 0,
  34.     ULength2 = 0,
  35.     VLength1 = 0,
  36.     VLength2 = 0,
  37.     ULength = Srf -> ULength,
  38.     VLength = Srf -> VLength,
  39.     UOrder = Srf -> UOrder,
  40.     VOrder = Srf -> VOrder;
  41.     CagdCrvStruct *Crv, *LCrv, *RCrv;
  42.     CagdSrfStruct
  43.     *RSrf = NULL,
  44.     *LSrf = NULL;
  45.  
  46.     switch (Dir) {
  47.     case CAGD_CONST_U_DIR:
  48.         for (Row = 0; Row < VLength; Row++) {
  49.         Crv = BspSrfCrvFromMesh(Srf, Row, CAGD_CONST_V_DIR);
  50.         LCrv = BspCrvSubdivAtParam(Crv, t);
  51.         RCrv = LCrv -> Pnext;
  52.  
  53.         if (Row == 0) {    /* Figure out surfaces size and allocate. */
  54.             ULength1 = LCrv -> Length;
  55.             ULength2 = RCrv -> Length;
  56.             LSrf = BspSrfNew(ULength1, VLength, UOrder, VOrder,
  57.                                 Srf -> PType);
  58.             RSrf = BspSrfNew(ULength2, VLength, UOrder, VOrder,
  59.                                 Srf -> PType);
  60.             CagdFree((VoidPtr) RSrf -> UKnotVector);
  61.             CagdFree((VoidPtr) RSrf -> VKnotVector);
  62.             CagdFree((VoidPtr) LSrf -> UKnotVector);
  63.             CagdFree((VoidPtr) LSrf -> VKnotVector);
  64.             RSrf -> UKnotVector = BspKnotCopy(RCrv -> KnotVector,
  65.                           RCrv -> Length + RCrv -> Order);
  66.             RSrf -> VKnotVector = BspKnotCopy(Srf -> VKnotVector,
  67.                           Srf -> VLength + Srf -> VOrder);
  68.             LSrf -> UKnotVector = BspKnotCopy(LCrv -> KnotVector,
  69.                           LCrv -> Length + LCrv -> Order);
  70.             LSrf -> VKnotVector = BspKnotCopy(Srf -> VKnotVector,
  71.                           Srf -> VLength + Srf -> VOrder);
  72.         }
  73.  
  74.         CagdCrvToMesh(LCrv, Row, CAGD_CONST_V_DIR, LSrf);
  75.         CagdCrvToMesh(RCrv, Row, CAGD_CONST_V_DIR, RSrf);
  76.  
  77.         CagdCrvFree(Crv);
  78.         CagdCrvFree(LCrv);
  79.         CagdCrvFree(RCrv);
  80.         }
  81.         break;
  82.     case CAGD_CONST_V_DIR:
  83.         for (Col = 0; Col < ULength; Col++) {
  84.         Crv = BspSrfCrvFromMesh(Srf, Col, CAGD_CONST_U_DIR);
  85.         LCrv = BspCrvSubdivAtParam(Crv, t);
  86.         RCrv = LCrv -> Pnext;
  87.  
  88.         if (Col == 0) {    /* Figure out surfaces size and allocate. */
  89.             VLength1 = LCrv -> Length;
  90.             VLength2 = RCrv -> Length;
  91.             LSrf = BspSrfNew(ULength, VLength1, UOrder, VOrder,
  92.                                 Srf -> PType);
  93.             RSrf = BspSrfNew(ULength, VLength2, UOrder, VOrder,
  94.                                 Srf -> PType);
  95.             CagdFree((VoidPtr) RSrf -> UKnotVector);
  96.             CagdFree((VoidPtr) RSrf -> VKnotVector);
  97.             CagdFree((VoidPtr) LSrf -> UKnotVector);
  98.             CagdFree((VoidPtr) LSrf -> VKnotVector);
  99.             RSrf -> UKnotVector = BspKnotCopy(Srf -> UKnotVector,
  100.                           Srf -> ULength + Srf -> UOrder);
  101.             RSrf -> VKnotVector = BspKnotCopy(RCrv -> KnotVector,
  102.                           RCrv -> Length + RCrv -> Order);
  103.             LSrf -> UKnotVector = BspKnotCopy(Srf -> UKnotVector,
  104.                           Srf -> ULength + Srf -> UOrder);
  105.             LSrf -> VKnotVector = BspKnotCopy(LCrv -> KnotVector,
  106.                           LCrv -> Length + LCrv -> Order);
  107.         }
  108.  
  109.         CagdCrvToMesh(LCrv, Col, CAGD_CONST_U_DIR, LSrf);
  110.         CagdCrvToMesh(RCrv, Col, CAGD_CONST_U_DIR, RSrf);
  111.  
  112.         CagdCrvFree(Crv);
  113.         CagdCrvFree(LCrv);
  114.         CagdCrvFree(RCrv);
  115.         }
  116.         break;
  117.     default:
  118.         FATAL_ERROR(CAGD_ERR_DIR_NOT_CONST_UV);
  119.         break;
  120.     }
  121.  
  122.     LSrf -> Pnext = RSrf;
  123.     return LSrf;
  124. }
  125.  
  126. /******************************************************************************
  127. * Return a new surface, identical to the original but with one degree higher  *
  128. * in the given direction.                              *
  129. ******************************************************************************/
  130. CagdSrfStruct *BspSrfDegreeRaise(CagdSrfStruct *Srf, CagdSrfDirType Dir)
  131. {
  132.     FATAL_ERROR(CAGD_ERR_NOT_IMPLEMENTED);
  133.  
  134.     return NULL;
  135. }
  136.  
  137. /******************************************************************************
  138. * Return a new surface equal to the derived surface in the direction Dir.     *
  139. * A test is made to make sure the original surface is not rational.          *
  140. * Let old control polygon be P(i), i = 0 to k-1, and Q(i) be new one then:    *
  141. * Q(i) = (k - 1) * P(i+1) - P(i), i = 0 to k-2.                      *
  142. * This is applied to all rows/cols of the surface.                  *
  143. ******************************************************************************/
  144. CagdSrfStruct *BspSrfDerive(CagdSrfStruct *Srf, CagdSrfDirType Dir)
  145. {
  146.     CagdBType
  147.     IsNotRational = !CAGD_IS_RATIONAL_SRF(Srf);
  148.     int i, j, Row, Col,
  149.     ULength = Srf -> ULength,
  150.     VLength = Srf -> VLength,
  151.     UOrder = Srf -> UOrder,
  152.     VOrder = Srf -> VOrder,
  153.     MaxCoord = CAGD_NUM_OF_PT_COORD(Srf -> PType);
  154.     CagdSrfStruct
  155.         *DerivedSrf = NULL;
  156.  
  157.  
  158.     switch (Dir) {
  159.     case CAGD_CONST_V_DIR:
  160.         if (!IsNotRational || UOrder < 3)
  161.         FATAL_ERROR(CAGD_ERR_RAT_LIN_NO_SUPPORT);
  162.  
  163.         DerivedSrf = BspSrfNew(ULength - 1, VLength,
  164.                    UOrder - 1, VOrder, Srf -> PType);
  165.         GEN_COPY(DerivedSrf -> UKnotVector,
  166.              &Srf -> UKnotVector[1],
  167.              sizeof(CagdRType) * (ULength + UOrder - 2));
  168.         GEN_COPY(DerivedSrf -> VKnotVector,
  169.              Srf -> VKnotVector,
  170.              sizeof(CagdRType) * (VLength + VOrder));
  171.  
  172.                for (Row = 0; Row < VLength; Row++)
  173.         for (i = 0; i < ULength - 1; i++)
  174.             for (j = IsNotRational; j <= MaxCoord; j++)
  175.             DerivedSrf -> Points[j][DERIVED_SRF(i, Row)] =
  176.                             (ULength - 1) *
  177.                 (Srf -> Points[j][SRF(i + 1, Row)] -
  178.                  Srf -> Points[j][SRF(i, Row)]);
  179.         break;
  180.     case CAGD_CONST_U_DIR:
  181.         if (!IsNotRational || VOrder < 3)
  182.         FATAL_ERROR(CAGD_ERR_RAT_LIN_NO_SUPPORT);
  183.  
  184.         DerivedSrf = BspSrfNew(ULength, VLength - 1,
  185.                        UOrder, VOrder - 1, Srf -> PType);
  186.         GEN_COPY(DerivedSrf -> UKnotVector,
  187.              Srf -> UKnotVector,
  188.              sizeof(CagdRType) * (ULength + UOrder));
  189.         GEN_COPY(DerivedSrf -> VKnotVector,
  190.              &Srf -> VKnotVector[1],
  191.              sizeof(CagdRType) * (VLength + VOrder - 2));
  192.  
  193.         for (Col = 0; Col < ULength; Col++)
  194.         for (i = 0; i < VLength - 1; i++)
  195.             for (j = IsNotRational; j <= MaxCoord; j++)
  196.             DerivedSrf -> Points[j][DERIVED_SRF(Col, i)] =
  197.                             (VLength - 1) *
  198.                 (Srf -> Points[j][SRF(Col, i + 1)] -
  199.                  Srf -> Points[j][SRF(Col, i)]);
  200.         break;
  201.     default:
  202.         FATAL_ERROR(CAGD_ERR_DIR_NOT_CONST_UV);
  203.         break;
  204.     }
  205.  
  206.     return DerivedSrf;
  207. }
  208.  
  209. /******************************************************************************
  210. * Evaluate the tangent to a surface at a given point and given direction.     *
  211. ******************************************************************************/
  212. CagdVecStruct *BspSrfTangent(CagdSrfStruct *Srf, CagdRType u, CagdRType v,
  213.                              CagdSrfDirType Dir)
  214. {
  215.     CagdVecStruct
  216.     *Tangent = NULL;
  217.     CagdCrvStruct *Crv;
  218.  
  219.     switch (Dir) {
  220.     case CAGD_CONST_V_DIR:
  221.         Crv = BspSrfCrvFromSrf(Srf, v, Dir);
  222.         Tangent = BspCrvTangent(Crv, u);
  223.         CagdCrvFree(Crv);
  224.         break;
  225.     case CAGD_CONST_U_DIR:
  226.         Crv = BspSrfCrvFromSrf(Srf, u, Dir);
  227.         Tangent = BspCrvTangent(Crv, v);
  228.         CagdCrvFree(Crv);
  229.         break;
  230.     default:
  231.         FATAL_ERROR(CAGD_ERR_DIR_NOT_CONST_UV);
  232.         break;
  233.     }
  234.  
  235.     return Tangent;
  236. }
  237.  
  238. /******************************************************************************
  239. * Evaluate the normal of a surface at a given point.                  *
  240. ******************************************************************************/
  241. CagdVecStruct *BspSrfNormal(CagdSrfStruct *Srf, CagdRType u, CagdRType v)
  242. {
  243.     static CagdVecStruct Normal;
  244.     CagdVecStruct *V, T1, T2;
  245.  
  246.     V = BspSrfTangent(Srf, u, v, CAGD_CONST_U_DIR);
  247.     CAGD_COPY_VECTOR(T1, *V);
  248.  
  249.     V = BspSrfTangent(Srf, u, v, CAGD_CONST_V_DIR);
  250.     CAGD_COPY_VECTOR(T2, *V);
  251.  
  252.     /* The normal is the cross product of T1 and T2: */
  253.     Normal.Vec[0] = T1.Vec[1] * T2.Vec[2] - T1.Vec[2] * T2.Vec[1];
  254.     Normal.Vec[1] = T1.Vec[2] * T2.Vec[0] - T1.Vec[0] * T2.Vec[2];
  255.     Normal.Vec[2] = T1.Vec[0] * T2.Vec[1] - T1.Vec[1] * T2.Vec[0];
  256.  
  257.     CAGD_NORMALIZE_VECTOR(Normal);            /* Normalize the vector. */
  258.  
  259.     return &Normal;
  260. }
  261.  
  262. /******************************************************************************
  263. * Evaluate the normals of a surface at a mesh defined by subdividing the      *
  264. * parametric space int a grid of size UFineNess by VFineNess.              *
  265. * The normals are saved in a linear CagdVecStruct vector which is allocated   *
  266. * dynamically. Data is saved u inc. first.                      *
  267. * This routine much faster than evaluating normal per each point of such mesh.*
  268. ******************************************************************************/
  269. CagdVecStruct *BspSrfMeshNormals(CagdSrfStruct *Srf, int UFineNess,
  270.                                 int VFineNess)
  271. {
  272.     int i, j;
  273.     CagdRType u, v, UMin, UMax, VMin, VMax;
  274.     CagdVecStruct *Normals, *NPtr, *T, T1, T2;
  275.     CagdCrvStruct **UCurves, **VCurves, *UCrv, *VCrv;
  276.  
  277.     BspSrfDomain(Srf, &UMin, &UMax, &VMin, &VMax);
  278.     Normals = (CagdVecStruct *) CagdMalloc(sizeof(CagdVecStruct) * UFineNess *
  279.                                    VFineNess);
  280.  
  281.     UCurves = (CagdCrvStruct **) CagdMalloc(sizeof(CagdCrvStruct *) *
  282.                                    UFineNess);
  283.     VCurves = (CagdCrvStruct **) CagdMalloc(sizeof(CagdCrvStruct *) *
  284.                                    VFineNess);
  285.  
  286.     UFineNess--;
  287.     VFineNess--;
  288.     for (i = 0; i <= UFineNess; i++)            /* Prepare Iso U curves. */
  289.     UCurves[i] = BspSrfCrvFromSrf(Srf,
  290.                 UMin + (UMax - UMin) * ((CagdRType) i) / UFineNess,
  291.             CAGD_CONST_U_DIR);
  292.     for (j = 0; j <= VFineNess; j++)                /* Prepare Iso V curves. */
  293.     VCurves[j] = BspSrfCrvFromSrf(Srf,
  294.             VMin + (VMax - VMin) * ((CagdRType) j) / VFineNess,
  295.             CAGD_CONST_V_DIR);
  296.  
  297.     NPtr = Normals;
  298.     for (i = 0; i <= UFineNess; i++) {
  299.     UCrv = UCurves[i];
  300.     u = UMin + (UMax - UMin) * ((CagdRType) i) / UFineNess;
  301.  
  302.     for (j = 0; j <= VFineNess; j++) {
  303.         VCrv = VCurves[j];
  304.         v = VMin + (VMax - VMin) * ((CagdRType) j) / VFineNess;
  305.  
  306.         /* We need to copy the tangents as BspCrvTangent save it in as   */
  307.         /* static so the second call will overwrite first call value.    */
  308.         T = BspCrvTangent(UCrv, v);
  309.         CAGD_COPY_VECTOR(T1, *T);
  310.         T = BspCrvTangent(VCrv, u);
  311.         CAGD_COPY_VECTOR(T2, *T);
  312.  
  313.         /* The normal is the cross product of T1 and T2: */
  314.         NPtr -> Vec[0] = T1.Vec[1] * T2.Vec[2] - T1.Vec[2] * T2.Vec[1];
  315.         NPtr -> Vec[1] = T1.Vec[2] * T2.Vec[0] - T1.Vec[0] * T2.Vec[2];
  316.         NPtr -> Vec[2] = T1.Vec[0] * T2.Vec[1] - T1.Vec[1] * T2.Vec[0];
  317.  
  318.         CAGD_NORMALIZE_VECTOR(*NPtr);           /* Normalize the vector. */
  319.         NPtr++;
  320.     }
  321.     }
  322.  
  323.     for (i = 0; i <= UFineNess; i++) CagdCrvFree(UCurves[i]);
  324.     CagdFree(UCurves);
  325.     for (j = 0; j <= VFineNess; j++) CagdCrvFree(VCurves[j]);
  326.     CagdFree(VCurves);
  327.  
  328.     return Normals;
  329. }
  330.